package com.nononsenseapps.feeder.ui

import android.content.*
import android.os.Bundle
import android.view.View
import android.widget.*
import androidx.appcompat.app.AppCompatDelegate
import androidx.lifecycle.lifecycleScope
import com.gitee.wsl.android.ext.device.clipboardString
import com.gitee.wsl.struct.category.CategoryItemWarp
import com.kongzue.stacklabelview.StackLabel
import com.lxj.xpopup.XPopup
import com.nononsenseapps.feeder.db.ARG
import com.nononsenseapps.feeder.db.entity.FeedItem
import com.nononsenseapps.feeder.db.entity.FeedItemFeature
import com.nononsenseapps.feeder.db.room.ID_UNSET
import com.nononsenseapps.feeder.db.room.MEMO_FEED_ID
import com.nononsenseapps.feeder.db.room.upsert
import com.nononsenseapps.feeder.net.NetManager
import com.nononsenseapps.feeder.ui.base.CoroutineScopedActivity
import com.nononsenseapps.feeder.ui.tag.*
import com.nononsenseapps.feeder.util.*
import com.nononsenseapps.feeder.worker.requestFeedFullPageSync
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.net.URL
import java.util.regex.Pattern

abstract class AbstractEditFeetItemActivity : CoroutineScopedActivity() {
    protected var feedItemId: Long = ID_UNSET

    // Views and shit
    protected lateinit var textTitle: EditText
    protected lateinit var textUrl: EditText
    protected lateinit var textMemo: EditText
    private lateinit var imageButtonOk: ImageButton
    protected lateinit var stackLabelViewTag: StackLabel
    private lateinit var textView_newTag: TextView
    private lateinit var buttom_newTag: Button
    protected lateinit var stackLabelViewTags: StackLabel
    protected lateinit var featureSpinner: Spinner
    private lateinit var featureAdd: ImageView
    protected var currentItemTags = mutableListOf<String>()
    protected var feedItemUrl: String? = null
    protected var feedItemTitle: String = ""

    protected var item: FeedItem? = null

    val titlePattern: Pattern = Pattern.compile("""<title>(.*)</title>""")
    val ogTitlePattern = Pattern.compile("""<meta property="og:title" content="(.*)"""")
    val ogImagePatten = Pattern.compile("""<meta property="og:image" content="(.*)"""")

    lateinit var itemTagSelecter: ItemTagSelecter

    override fun onCreate(savedInstanceState: Bundle?) {
        if (shouldBeFloatingWindow()) {
            setupFloatingWindow()
        }
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_edit_favorite)

        // Not persisted so set nightmode every time we start
        AppCompatDelegate.setDefaultNightMode(settingsViewModel.themePreference)

        textTitle = findViewById(R.id.favorite_title)
        textUrl = findViewById(R.id.favorite_url)
        textMemo = findViewById(R.id.favorite_memo)
        imageButtonOk = findViewById(R.id.imageButton_ok)
        featureSpinner = findViewById(R.id.feature_spinner)
        featureAdd = findViewById(R.id.feature_add_imageView)

        featureAdd.setOnClickListener {
            XPopup.Builder(this).asInputConfirm(getString(R.string.feature_add), "") { text ->
                text.isNotEmpty().isTrue {
                    item?.let {
                        lifecycleScope.launch(Dispatchers.IO) {
                            val featureItem = FeedItemFeature(
                                title = text
                                    ?: ""
                            )
                            feedItemFeatureDao.insert(featureItem).let {
                                item?.feature = it
                                featureItem.id = it
                                withContext(Dispatchers.Main) {
                                    featureAdapter.add(featureItem)
                                    selectFeature(it)
                                }
                            }
                        }
                    }
                }
            }.show()
        }

        featureSpinner.adapter = featureAdapter

        featureSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onNothingSelected(parent: AdapterView<*>?) {
                item?.let {
                    it.feature = null
                }
            }

            override fun onItemSelected(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long
            ) {
                item?.let {
                    val featureId = featureAdapter.getItem(position)?.id?:ID_UNSET
                    if (featureId == ID_UNSET)
                        it.feature = null
                    else
                        it.feature = featureId
                }
            }
        }

        imageButtonOk.setOnClickListener {
            if(updateSaveBefore()) {
                lifecycleScope.launch(Dispatchers.IO) {
                    feedItemId = feedItemDao.upsert(item!!)
                    globalViewModel.checkFeedItemTag(currentItemTags)
                    if(item?.fullTextSync == true)
                        requestFeedFullPageSync(applicationContext)
                    withContext(Dispatchers.Main) {
                        makeToast(getString(R.string.feed_favorite_success))
                        finish()
                    }
                }
            }
        }

        // Consider start intent

        if (intent != null) {
            // Existing id
            feedItemId = intent.getLongExtra(ARG.FEED_ITEM_ID, ID_UNSET)
        }

        if (feedItemId > ID_UNSET) {
            lifecycleScope.launch(Dispatchers.IO) {
                item = feedItemDao.loadFeedItem(feedItemId) ?: newItem()
                item?.let {
                    withContext(Dispatchers.Main) {
                        textUrl.setText(it.link)
                        textTitle.setText(it.plainTitle)
                        textMemo.setText(it.plainSnippet)
                        stackLabelViewTag.setLabels(it.itemTags.split(","))
                        item?.feature?.let {
                            selectFeature(it)
                        }
                    }
                }
            }
        } else {
            item = newItem()
        }

        val shardStr = (intent.dataString ?: intent.getStringExtra(Intent.EXTRA_TEXT)?: intent.getStringExtra(Intent.EXTRA_PROCESS_TEXT) ?: "").trim()

        // Link
        feedItemUrl = naiveFindUrlLink(shardStr) ?: ""
        // URL
        textUrl.setText(feedItemUrl)

        // Title
        feedItemTitle = shardStr.replace(feedItemUrl!!, "")
        intent.getStringExtra(ARG.TITLE)?.let {
            feedItemTitle = it
        }
        val customTitle = intent.getStringExtra(ARG.CUSTOM_TITLE) ?: ""
        if (intent.hasExtra(ARG.CUSTOM_TITLE) && customTitle.isNotBlank()) {
            textTitle.setText(customTitle)
        } else {
            if(feedItemTitle.length>30){
                textMemo.setText(feedItemTitle)
                feedItemTitle = feedItemTitle.substring(0,25)
            }
            textTitle.setText(feedItemTitle)
        }

        stackLabelViewTag = findViewById(R.id.stackLabelView_tag)
        stackLabelViewTag.setOnLabelClickListener { index, _, s ->
            stackLabelViewTag.remove(index)
            //settingsViewModel.removeHistoryItemTag(s)
            currentItemTags.remove(s)
        }

        stackLabelViewTags = findViewById(R.id.stackLabelView_all_tag)
        stackLabelViewTags.setOnLabelClickListener { _, _, s ->
           tagClick(s)
        }


        textView_newTag = findViewById(R.id.textView_newTag)
        buttom_newTag = findViewById(R.id.button_add_tag)
        buttom_newTag.setOnClickListener {
            textView_newTag.text?.isNotEmpty().isTrue {
                val s = textView_newTag.text.toString().trim()
                if (!stackLabelViewTag.isHave(s)) {
                    stackLabelViewTag.addLabel(s)
                    currentItemTags.add(s)
                    settingsViewModel.addHistoryItemTag(s)
                }
            }
        }

        if (feedItemId == ID_UNSET) {
            if (textTitle.text.isNullOrEmpty()) {
                if (feedItemUrl.isNullOrEmpty()) {
                   /* copyFromClipboard(this)*/
                    clipboardString?.let{ content ->
                        textMemo.setText(content)
                        naiveFindUrlLink(content)?.let {
                            feedItemUrl = it
                            // URL
                            textUrl.setText(feedItemUrl)

                            textMemo.setText(content.replace(feedItemUrl!!, ""))
                        }
                    }
                } else {
                    loadUrlTitle(feedItemUrl!!)
                }
            } else {
                updateTitle(textTitle.text.toString())
            }
        }

        lifecycleScope.launch(Dispatchers.IO) {
            initFeatureAdapter(globalViewModel.feedItemFeatureList())
        }
        initItemTagsUI()
    }

    fun updateSaveBefore(): Boolean {
        val url=textUrl.text?.toString()
        //if(url.isNullOrEmpty()) return false
        item?.apply {
            title = textTitle.text?.toString() ?: ""
            plainTitle = textTitle.text?.toString() ?: ""
            link = url
            itemTags = currentItemTags.joinToString(",")
            plainSnippet = textMemo.text?.toString() ?: ""
            if (feedItemId == ID_UNSET) {
                if(!url.isNullOrEmpty()) {
                    fullTextSync = true
                    if (feedId == MEMO_FEED_ID) {
                        description =
                            getString(com.nononsenseapps.feeder.core.R.string.full_page_loading)
                    } else {
                        plainSnippet =
                            getString(com.nononsenseapps.feeder.core.R.string.full_page_loading)
                        description = textMemo.text?.toString() ?: ""
                    }
                }else if (feedId == MEMO_FEED_ID)
                    description = plainSnippet
            }
        }
        return true
    }



    private fun initItemTagsUI() {
        settingsViewModel.historyTags.toList().forEach {
            stackLabelViewTags.addLabel(it)
        }

        val repository = object : AdapterItemTagRepository(globalViewModel) {
            override fun contextScope(): CoroutineScope = lifecycleScope
        }

        val itemTagClickAdapter =object : AbstractItemTagClickCallBack() {
            override fun onItemTagClick(itemTagWap: CategoryItemWarp) {
                super.onItemTagClick(itemTagWap)
                tagClick(repository.getItemWarpTitle(itemTagWap))
            }
        }

        lifecycleScope.launch {
            itemTagSelecter = ItemTagSelecter(
                findViewById(R.id.item_tag_select),
                itemTagClickAdapter,
                repository
            ) { _, _, tag -> tagClick(tag) }

        }
    }

    private fun tagClick(tag: String?) {
        tag?.let {
            if (!stackLabelViewTag.isHave(tag)) {
                stackLabelViewTag.addLabel(tag)
                currentItemTags.add(tag)
            }
        }
    }


    private fun loadUrlTitle(url: String) {
        textTitle.setText(getString(R.string.background_loading))
        lifecycleScope.launch(Dispatchers.IO) {
            var title = ""
            try {
                NetManager.defaultNetManager.curl(URL(url))?.let {
                    val titleMatcher = titlePattern.matcher(it)
                    if (titleMatcher.find()) {
                        title = titleMatcher.group(1)?.toString() ?: ""
                    }
                    if (title.isEmpty()) {
                        val ogTitleMatcher = ogTitlePattern.matcher(it)
                        if (ogTitleMatcher.find()) {
                            title = ogTitleMatcher.group(1)?.toString() ?: ""
                        }
                    }
                    val ogImageMatcher = ogImagePatten.matcher(it)
                    if (ogImageMatcher.find())
                        item?.imageUrl = ogImageMatcher.group(1)?.toString()
                }
            } catch (e: Exception) {
                Timber.d(e, "load url title exception")
            }
            withContext(Dispatchers.Main) {
                updateTitle(title)
            }
        }
    }

    private fun updateTitle(title: String) {
        textTitle.setText(title)
        lifecycleScope.launch(Dispatchers.IO) {
            val tags = NlpUtils.buildTags(title)
            withContext(Dispatchers.Main) {
                tags.forEach {
                    if (!stackLabelViewTags.isHave(it))
                        stackLabelViewTags.addLabel(it)
                }
            }
        }
    }

    abstract fun newItem(): FeedItem

    private fun selectFeature(featureId: Long) {
        var selectIndex = 0
        if (featureId > ID_UNSET) {
            for (index in 0 until featureAdapter.count) {
                if (featureAdapter.getItem(index)?.id == featureId)
                    selectIndex = index
            }
        }
        featureSpinner.setSelection(selectIndex)
        Timber.d("spinner selected index:$selectIndex,featureId:$featureId,current Item feature:${item?.feature}")
    }
}